﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace zibaomaoPC
{
    class Program
    {
        static String serverAddr = "https://127.0.0.1:25555";
        static int USER_OPERATION_TIMEOUT = 3;//每个人的动作是10秒
        static bool showHttpStr = true;
        //本地测试地址
        //static String serverAddr = "http://www.yaasoosoft.com:25555";
        static readonly HttpClient client = new HttpClient();
        //json忽略NULL值
        static JsonSerializer jsonSettings = new JsonSerializer
        {
            NullValueHandling = NullValueHandling.Ignore
        };
        static JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
        {
            Converters = new JsonConverter[] { new Newtonsoft.Json.Converters.StringEnumConverter() }
        };

        static void Main(string[] args)
        {
            // 禁用SSL/TLS验证
            System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

            createUser("lisi", "12345678");
            createUser("lisi2", "12345678");
            GameUser gm = testLogin("zhangsan", "12345678");
            GameUser gm2 = testLogin("lisi", "12345678");
            if (gm != null && gm2 != null)
            {
                getUserInfo(gm);
                heartbeat(gm);
                System.Threading.Thread.Sleep(4000);//休眠4秒，心跳3秒超时
                getUserInfo(gm);
                Room rm = createRoom(gm);
                if (rm == null)
                {
                    rm = new Room();
                    rm.id = gm.roomNumber;
                }
                getRoomInfo(gm);
                System.Threading.Thread.Sleep(1000);//休眠1秒

                gm2.roomNumber = rm.id;//想要加入的房间ID
                joinRoom(gm2);//用户2加入房间
                System.Threading.Thread.Sleep(1000);//休眠1秒
                getRoomInfo(gm);
                System.Threading.Thread.Sleep(1000);//休眠1秒

                startGame(gm);//房管才能开始游戏
                while (true)
                {
                    Deck dk = getDeckInfo(gm);
                    if (dk == null)
                        break;
                    if (!dk.state.Equals("START"))//等待游戏结束，客户端结束，服务端任然会运行
                    {
                        Console.WriteLine("=================================\nwinner:" + dk.winPlayer);
                        break;
                    }
                    if (dk.currentUserID == gm.id)//轮到自己就直接操作
                    {
                        DeckManage deckManage = new DeckManage();
                        deckManage.gameUser = gm;
                        deckManage.roomId = rm.id;
                        int index = Array.IndexOf(dk.userOperate, Deck.USER_OPERATE.PLAY_CARD);
                        if (index >= 0)//当前允许打牌
                        {
                            List<BaseCard> user2Cards = dk.Users[gm.id];
                            foreach (BaseCard gu in user2Cards)
                            {
                                if (gu.cardType == BaseCard.TurnCard)//模拟打转向牌，现在普通牌不能打，只是测试用的
                                {
                                    deckManage.cardBase = gu;
                                    break;
                                }
                                else if (gu.cardType == BaseCard.SkipCard)//模拟打跳过牌，现在普通牌不能打，只是测试用的
                                {
                                    deckManage.cardBase = gu;
                                    break;
                                }
                            }
                            if(deckManage.cardBase!=null)//手上有转向牌
                            {
                                deckManage.userOperate = DeckManage.USER_OPERATE.PLAY_CARD;
                            }
                            else//只能摸牌了
                            {
                                deckManage.userOperate = DeckManage.USER_OPERATE.DRAW_CARD;
                            }
                            doOperate(deckManage);//户开始操作
                        }
                        else if (dk.userOperate[0] == Deck.USER_OPERATE.PLAY_DEFUSE_CARD)//当前必须出拆
                        {
                            deckManage.userOperate = DeckManage.USER_OPERATE.PLAY_DEFUSE_CARD;
                            List<BaseCard> user2Cards = dk.Users[gm.id];
                            foreach (BaseCard gu in user2Cards)
                            {
                                if (gu.cardType == BaseCard.DefuseCard)
                                {
                                    deckManage.cardBase = gu;
                                    break;
                                }
                            }
                            doOperate(deckManage);//如果没有拆，也要打牌
                        }
                        else
                        {

                        }
                    }
                    Console.WriteLine("lastPlayer:" + dk.lastPlayer);
                    Console.WriteLine("last operate:" + dk.lastUserOperate);
                    Console.WriteLine("remainRounds:" + dk.remainRounds);//剩余回合数，每个人需要摸几次牌，或者打几次牌
                    if (dk.lastUserOperate != Deck.USER_OPERATE.DRAW_CARD)//抓牌是看不到的，其它打牌等可以看到用户出的牌
                    {
                        Console.WriteLine("last playCard:" + dk.lastPlayCard);
                    }
                    System.Threading.Thread.Sleep(1 * 1000);
                }


                //把用户2踢出房间
                RoomManage roomManage = new RoomManage();
                roomManage.masterUser = gm;
                roomManage.roomId = rm.id;
                roomManage.userId = gm2.id;
                kickRoom(roomManage);

                joinRoom(gm2);//用户2加入房间
                System.Threading.Thread.Sleep(1000);//休眠1秒
                getRoomInfo(gm);
                System.Threading.Thread.Sleep(1000);//休眠1秒

                exitRoom(gm);//房主退出，gm2成为房主
                System.Threading.Thread.Sleep(1000);//休眠1秒
                getRoomInfo(gm);
                exitRoom(gm2);//房主退出
                System.Threading.Thread.Sleep(1000);//休眠1秒
                //当房间所有人都退出时，房间自动销毁
                getRoomInfo(gm);
            }
            Console.WriteLine("any key to exit");
            Console.ReadKey();
        }

        private static void startGame(GameUser gameUser)
        {
            // 设置要提交的数据
            Dictionary<string, string> myDictionary = new Dictionary<string, string>();
            // 向 Dictionary 中添加键值对  
            myDictionary.Add("selfid", "" + gameUser.id);
            myDictionary.Add("token", gameUser.token);

            String res = getMsg("/startGame", myDictionary);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                ServerRet ret = jsonObject.ToObject<ServerRet>(jsonSettings);
                if (ret.code != 200)
                {
                    Console.WriteLine("error：" + jsonObject.GetValue("msg"));
                    return;
                }
                Console.WriteLine("start game success：");

            }
            catch (Exception e)
            {
                Console.WriteLine("server error " + e);
            }
        }

        private static Deck getDeckInfo(GameUser gameUser)
        {
            // 设置要提交的数据
            Dictionary<string, string> myDictionary = new Dictionary<string, string>();
            // 向 Dictionary 中添加键值对  
            myDictionary.Add("selfid", "" + gameUser.id);
            myDictionary.Add("token", gameUser.token);

            String res = getMsg("/getDeckInfo", myDictionary);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                ServerRet ret = jsonObject.ToObject<ServerRet>(jsonSettings);
                if (ret.code != 200)
                {
                    Console.WriteLine("error：" + jsonObject.GetValue("msg"));
                    return null;
                }
                Deck deck = jsonObject.GetValue("obj").ToObject<Deck>(jsonSettings);
                if (deck != null)
                {
                    Console.WriteLine("当前轮到谁操作：" + deck.currentUserID);
                    Console.WriteLine("当前打牌方向：" + deck.currentDirection);
                    Console.WriteLine("当前游戏状态：" + deck.state);
                    if (deck.Users.ContainsKey(gameUser.id))
                    {
                        List<BaseCard> user2Cards = deck.Users[gameUser.id];
                        foreach (BaseCard gu in user2Cards)
                        {
                            Console.WriteLine("当前用户有卡片：" + gu.ToString());
                        }
                    }
                    return deck;
                }
                else
                {
                    Console.WriteLine("请检查当前用户和房间ID");
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("server error " + e);
            }
            return null;
        }

        private static Deck doOperate(DeckManage deckManage)
        {
            String res = postMsg("/doOperate", deckManage);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                ServerRet ret = jsonObject.ToObject<ServerRet>(jsonSettings);
                if (ret.code != 200)
                {
                    Console.WriteLine("error：" + jsonObject.GetValue("msg"));
                    return null;
                }

                Deck deck = jsonObject.GetValue("obj").ToObject<Deck>(jsonSettings);
                if (deck != null)
                {
                    Console.WriteLine("当前轮到谁操作：" + deck.currentUserID);
                    Console.WriteLine("当前打牌方向：" + deck.currentDirection);
                    Console.WriteLine("当前游戏状态：" + deck.state);
                    if (deck.Users.ContainsKey(deckManage.gameUser.id))
                    {
                        List<BaseCard> user2Cards = deck.Users[deckManage.gameUser.id];
                        foreach (BaseCard gu in user2Cards)
                        {
                            Console.WriteLine("当前用户有卡片：" + gu.ToString());
                        }
                    }
                    return deck;
                }
                else
                {
                    Console.WriteLine("摸牌失败");
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("server error " + e);
            }
            return null;
        }
        private static GameUser createUser(string name, string pswd)
        {
            // 设置要提交的数据
            Dictionary<string, string> myDictionary = new Dictionary<string, string>();
            // 向 Dictionary 中添加键值对  
            myDictionary.Add("username", name);
            myDictionary.Add("password", pswd);

            String res = getMsg("/createUser", myDictionary);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                ServerRet ret = jsonObject.ToObject<ServerRet>(jsonSettings);
                if (ret.code != 200)
                {
                    Console.WriteLine("error：" + jsonObject.GetValue("msg"));
                    return null;
                }
                GameUser person = jsonObject.GetValue("obj").ToObject<GameUser>(jsonSettings);
                if (person != null)
                {
                    Console.WriteLine("用户ID-唯一身份标识：" + person.id);
                    Console.WriteLine("用户在线状态：" + person.online);
                    Console.WriteLine("用户当前所在房号（!=0）：" + person.roomNumber);
                }
                else
                {
                    Console.WriteLine("创建用户失败");
                }
                return person;
            }
            catch (Exception e)
            {
                Console.WriteLine("server error " + e);
            }
            return null;
        }
        private static void exitRoom(GameUser gameUser)
        {
            // 设置要提交的数据
            Dictionary<string, string> myDictionary = new Dictionary<string, string>();
            // 向 Dictionary 中添加键值对  
            myDictionary.Add("selfid", "" + gameUser.id);
            myDictionary.Add("token", gameUser.token);

            String res = getMsg("/exitRoom", myDictionary);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                int code = (int)jsonObject["code"];
                if (code == 200)
                {
                    Console.WriteLine("退出房间正常 ");
                }
                else if (code == 401)
                {
                    Console.WriteLine("用户在其它设备登录，退出失败");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("server error " + e);
            }
        }
        private static Room joinRoom(GameUser gameUser)
        {
            String res = postMsg("/joinRoom", gameUser);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                ServerRet ret = jsonObject.ToObject<ServerRet>(jsonSettings);
                if (ret.code != 200)
                {
                    Console.WriteLine("error：" + jsonObject.GetValue("msg"));
                    return null;
                }
                Room room = jsonObject.GetValue("obj").ToObject<Room>(jsonSettings);
                if (room != null)
                {
                    Console.WriteLine("房间ID-唯一身份标识：" + room.id);
                    Console.WriteLine("房间名：" + room.name);
                    Console.WriteLine("房间房管-用户ID：" + room.roomMaster);
                    foreach (long id in room.saveUsers)
                    {
                        Console.WriteLine("房间里的用户有：" + id);
                    }
                }
                else
                {
                    Console.WriteLine("请退出当前房间再加入");
                }
                return room;
            }
            catch (Exception e)
            {
                Console.WriteLine("请退出当前房间再加入 " + e);
            }
            return null;
        }
        private static Room kickRoom(RoomManage roomManage)
        {
            String res = postMsg("/kickRoom", roomManage);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                ServerRet ret = jsonObject.ToObject<ServerRet>(jsonSettings);
                if (ret.code != 200)
                {
                    Console.WriteLine("error：" + jsonObject.GetValue("msg"));
                    return null;
                }
                Room room = jsonObject.GetValue("obj").ToObject<Room>(jsonSettings);
                if (room != null)
                {
                    Console.WriteLine("房间ID-唯一身份标识：" + room.id);
                    Console.WriteLine("房间名：" + room.name);
                    Console.WriteLine("房间房管-用户ID：" + room.roomMaster);
                    foreach (long id in room.saveUsers)
                    {
                        Console.WriteLine("房间里的用户有：" + id);
                    }
                }
                else
                {
                    Console.WriteLine("kickRoom失败");
                }
                return room;
            }
            catch (Exception e)
            {
                Console.WriteLine("kickRoom失败 " + e);
            }
            return null;
        }
        private static Room createRoom(GameUser gm)
        {

            String res = postMsg("/createRoom", gm);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                ServerRet ret = jsonObject.ToObject<ServerRet>(jsonSettings);
                if (ret.code != 200)
                {
                    Console.WriteLine("error：" + jsonObject.GetValue("msg"));
                    return null;
                }
                Room room = jsonObject.GetValue("obj").ToObject<Room>(jsonSettings);
                if (room != null)
                {
                    Console.WriteLine("房间ID-唯一身份标识：" + room.id);
                    Console.WriteLine("房间名：" + room.name);
                    Console.WriteLine("房间房管-用户ID：" + room.roomMaster);
                    foreach (long id in room.saveUsers)
                    {
                        Console.WriteLine("房间里的用户有：" + id);
                    }
                }
                else
                {
                    Console.WriteLine("请退出当前房间再创建");
                }
                return room;
            }
            catch (Exception e)
            {
                Console.WriteLine("创建失败 " + e);
            }
            return null;
        }
        private static void getRoomInfo(GameUser gameUser)
        {
            // 设置要提交的数据
            Dictionary<string, string> myDictionary = new Dictionary<string, string>();
            // 向 Dictionary 中添加键值对  
            myDictionary.Add("selfid", "" + gameUser.id);
            myDictionary.Add("token", gameUser.token);

            String res = getMsg("/getRoomInfo", myDictionary);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                ServerRet ret = jsonObject.ToObject<ServerRet>(jsonSettings);
                if (ret.code != 200)
                {
                    Console.WriteLine("error：" + jsonObject.GetValue("msg"));
                    return;
                }
                Room room = jsonObject.GetValue("obj").ToObject<Room>(jsonSettings);
                if (room != null)
                {
                    Console.WriteLine("房间ID-唯一身份标识：" + room.id);
                    Console.WriteLine("房间名：" + room.name);
                    Console.WriteLine("房间房管-用户ID：" + room.roomMaster);
                    foreach (GameUser gu in room.users)
                    {
                        Console.WriteLine("房间里的用户有：" + gu.id + " " + gu.username + " " + gu.online);
                    }
                }
                else
                {
                    Console.WriteLine("请检查当前用户和房间ID");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("server error " + e);
            }
        }
        private static void getUserInfo(GameUser gameUser)
        {
            // 设置要提交的数据
            Dictionary<string, string> myDictionary = new Dictionary<string, string>();
            // 向 Dictionary 中添加键值对  
            myDictionary.Add("selfid", "" + gameUser.id);
            myDictionary.Add("token", gameUser.token);

            String res = getMsg("/getUserInfo", myDictionary);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                JToken user = jsonObject.GetValue("obj");
                GameUser person = user.ToObject<GameUser>(jsonSettings);
                Console.WriteLine("用户ID-唯一身份标识：" + person.id);
                Console.WriteLine("用户在线状态：" + person.online);
                Console.WriteLine("用户当前所在房号（!=0）：" + person.roomNumber);
            }
            catch (Exception e)
            {
                Console.WriteLine("server error " + e);
            }
        }

        static String postMsg(String api, Object obj)
        {
            try
            {
                // 将JSON数据转换为字符串  
                var jsonContent = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(obj, jsonSerializerSettings), Encoding.UTF8, "application/json");
                var pt = jsonContent.ReadAsStringAsync();
                pt.Wait();
                if (showHttpStr)
                {
                    Console.WriteLine("post json:" + pt.Result);
                }

                // 执行POST请求  
                var responseTask = client.PostAsync(serverAddr + api, jsonContent);

                responseTask.Wait();
                // 处理响应结果  
                if (responseTask.Result.IsSuccessStatusCode)
                {
                    var responseContent = responseTask.Result.Content.ReadAsStringAsync();
                    if (showHttpStr)
                        Console.WriteLine(responseContent.Result);
                    return responseContent.Result;
                }
                else
                {
                    Console.WriteLine("请求失败");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("post error " + e);
            }
            return "";
        }
        static String getMsg(String api, Dictionary<string, string> myDictionary)
        {
            String url = serverAddr + api + "?";
            // 遍历 Dictionary 中的所有键值对  
            foreach (KeyValuePair<string, string> pair in myDictionary)
            {
                string kv = pair.Key + "=" + pair.Value + "&";
                Console.WriteLine(kv);
                url += kv;
            }
            if (showHttpStr)
                Console.WriteLine(url);
            try
            {
                // 执行POST请求  
                var responseTask = client.GetAsync(url);
                responseTask.Wait();
                // 处理响应结果  
                if (responseTask.Result.IsSuccessStatusCode)
                {
                    var responseContent = responseTask.Result.Content.ReadAsStringAsync();
                    if (showHttpStr)
                        Console.WriteLine(responseContent.Result);
                    return responseContent.Result;
                }
                else
                {
                    Console.WriteLine("请求失败");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("get error " + e);
            }
            return "";
        }
        static GameUser testLogin(string name, string pswd)
        {
            // 设置要提交的数据
            var loginData = new LoginEntity();
            loginData.username = name;
            loginData.password = pswd;
            String res = postMsg("/login", loginData);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                ServerRet ret = jsonObject.ToObject<ServerRet>(jsonSettings);
                if (ret.code != 200)
                {
                    Console.WriteLine("error：" + jsonObject.GetValue("msg"));
                    return null;
                }
                GameUser person = jsonObject.GetValue("obj").ToObject<GameUser>(jsonSettings);
                if (person != null)
                {
                    Console.WriteLine("用户ID-唯一身份标识：" + person.id);
                    Console.WriteLine("用户在线状态：" + person.online);
                    Console.WriteLine("用户当前所在房号（!=0）：" + person.roomNumber);
                }
                else
                {
                    Console.WriteLine("创建用户失败");
                }
                return person;
            }
            catch (Exception e)
            {
                Console.WriteLine("登录失败 " + e);
            }
            return null;
        }
        static void heartbeat(GameUser gameUser)
        {
            // 设置要提交的数据
            Dictionary<string, string> myDictionary = new Dictionary<string, string>();
            // 向 Dictionary 中添加键值对  
            myDictionary.Add("selfid", "" + gameUser.id);
            myDictionary.Add("token", gameUser.token);

            String res = getMsg("/heartbeat", myDictionary);
            try
            {
                JObject jsonObject = JObject.Parse(res);
                int code = (int)jsonObject["code"];
                if (code == 200)
                {
                    Console.WriteLine("心跳正常 ");
                }
                else if (code == 401)
                {
                    Console.WriteLine("用户在其它设备登录");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("server error " + e);
            }
        }
    }
}
